package com.chenglai.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.chenglai.commonutils.common.DateFormatHelper;
import com.chenglai.commonutils.common.PayUtil;
import com.chenglai.commonutils.common.RequestHandler;
import com.chenglai.commonutils.common.Util;
import com.chenglai.pay.config.WxConfig;
import com.chenglai.pay.dao.PayInfoMapper;
import com.chenglai.pay.dao.RefundInfoMapper;
import com.chenglai.pay.dao.ShopSecretMapper;
import com.chenglai.pay.entry.MainOrder;
import com.chenglai.pay.feign.GroupService;
import com.chenglai.pay.feign.OrderService;
import com.chenglai.pay.feign.SeckillService;
import com.chenglai.pay.pojo.PayInfo;
import com.chenglai.pay.pojo.RefundInfo;
import com.chenglai.pay.pojo.ShopSecret;
import com.chenglai.pay.service.PayService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 类描述：
 *
 * @Author rxh
 * @Date 2023/11/21 10:40
 */
@Service
public class PayServiceImpl implements PayService {

    @Resource
    private WxConfig wxConfig;

    @Resource
    private ShopSecretMapper shopSecretMapper;

    @Resource
    private OrderService orderService;

    @Resource
    private PayInfoMapper payInfoMapper;

    @Resource
    private RefundInfoMapper refundInfoMapper;

    @Resource
    private SeckillService seckillService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private GroupService groupService;

    @Override
    public Map getPackages(Integer shopId, String orderNum, Double totalNum, String shopName, String scene, String sceneInfo, String openId, Integer userId,HttpServletRequest request) {
        Map<String, Object> map = pay(shopId, totalNum, orderNum, shopName, scene, sceneInfo, openId, userId,request);
        return map;
    }

    @Override
    public void getSuccess(HttpServletRequest request, HttpServletResponse response) {
        String resXml = "";
        InputStream inStream;
        try {
            inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            String result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
            Map m = PayUtil.parseXmlToList2(result);
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            if ("SUCCESS".equals(m.get("result_code").toString())) {
                // 更新支付状态
                String orderNum = m.get("out_trade_no").toString();
                String transactionId = m.get("transaction_id").toString();
                Integer attach = (Integer) m.get("attach");
                //调用订单服务，修改订单状态
                orderService.updateOrderStatus(orderNum, 1, transactionId);
                //添加支付记录
//                PayInfo payInfo = new PayInfo();
//                payInfo.setOrderNum(orderNum);
//                payInfo.setTransactionId(transactionId);
//                payInfo.setPayNum(totalFee);
//                payInfo.setPayForm(0);
//                payInfo.setPayTime(DateFormatHelper.currentTimes());
//                payInfoMapper.insert(payInfo);

                MainOrder mainOrder = JSON.parseObject((String)redisTemplate.opsForHash().get("orders_"+attach,"m_"+orderNum),MainOrder.class);
                //判断是正常下单还是开团还是参团

                Integer orderFlag = Integer.parseInt(mainOrder.getOrderFrom());
                if(orderFlag!=0){
                    Map maps = new HashMap();
                    maps.put("groupNum",mainOrder.getGroupNum());
                    maps.put("userId",mainOrder.getUserId());
                    maps.put("groupId",mainOrder.getGroupId());
                    maps.put("orderNum",orderNum);
                    maps.put("flag",orderFlag);
                    //添加开团信息以及团购详情
                    groupService.addGroupOnOrDetail(maps);
                    maps = null;
                }
                //清空订单记录信息
                redisTemplate.opsForHash().delete("orders_"+attach);
                resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";

            } else {
                resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";

            }
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public Map refund(String transactionId, Integer shopId, Double totalNum, Double refundFee, String refundDesc) {
        Map<String, Object> data = new HashMap();
        data.put("flag", "error");
        data.put("msg", "申请退款失败");
        SortedMap<String, Object> packageParams = new TreeMap<>();
        ShopSecret secret = shopSecretMapper.getSecret(shopId);
        String nonceStr = DateFormatHelper.getCurTimestamp().toString();
        String refundNo = String.valueOf(new Date().getTime());
        packageParams.put("appid", wxConfig.getAppId());
        packageParams.put("mch_id", secret.getShopPartner());
        packageParams.put("nonce_str", nonceStr);
        packageParams.put("transaction_id", transactionId);
        packageParams.put("out_refund_no", refundNo);
        packageParams.put("total_fee", Util.getMoney(totalNum.toString()));
        packageParams.put("refund_fee", Util.getMoney(refundFee.toString()));
        packageParams.put("refund_desc", refundDesc);
        packageParams.put("notify_url", wxConfig.getRefundNotifyUrl());

        RequestHandler requestHandler = new RequestHandler(null, null);
        requestHandler.init(wxConfig.getAppId(), wxConfig.getAppSecret(), secret.getShopPartnerkey(), secret.getShopPartner());
        String sign = requestHandler.createSign(packageParams);

        String xml = "<xml>" +
                "   <appid>" + wxConfig.getAppId() + "</appid>" +
                "   <mch_id>" + secret.getShopPartner() + "</mch_id>" +
                "   <nonce_str>" + nonceStr + "</nonce_str>" +
                "   <out_refund_no>" + refundNo + "</out_refund_no>" +
                "   <transaction_id>" + transactionId + "</transaction_id>" +
                "   <refund_fee>" + Util.getMoney(refundFee.toString()) + "</refund_fee>" +
                "   <total_fee>" + Util.getMoney(totalNum.toString()) + "</total_fee>" +
                "   <refund_desc>" + refundDesc + "</refund_desc>" +
                "   <notify_url>" + wxConfig.getRefundNotifyUrl() + "</notify_url>" +
                "   <sign>" + sign + "</sign>" +
                "</xml>";

        String result = PayUtil.httpRequest(wxConfig.getRefundUrl(), "POST", xml);
        try {
            Map map = PayUtil.doXMLParse(result);
            String returnCode = map.get("return_code").toString();
            if ("SUCCESS".equals(returnCode)) {
                data.put("flag", "success");
                data.put("msg", "申请退款成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }

    @Override
    public void refundSuccess(HttpServletRequest request, HttpServletResponse response) {
        String resXml = "";
        InputStream inStream;
        try {
            inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            String result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
            Map m = PayUtil.parseXmlToList2(result);
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            if ("SUCCESS".equals(m.get("result_code").toString())) {
                String refundNo = m.get("out_refund_no").toString();
                String transactionId = m.get("transaction_id").toString();
                Integer refundFee = (Integer) m.get("settlement_refund_fee");
                //调用订单服务，修改订单状态
                orderService.updateOrderRefundStatus(transactionId, 5);
                //添加退款记录
                RefundInfo refundInfo = new RefundInfo();
                refundInfo.setRefundNo(refundNo);
                refundInfo.setTransactionId(transactionId);
                refundInfo.setRefundDesc("");
                refundInfo.setRefundFee(refundFee);
                refundInfo.setRefundTime(DateFormatHelper.currentTimes());
                refundInfoMapper.insert(refundInfo);
                resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";

            } else {
                resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";

            }
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Map<String, Object> pay(Integer shopId, Double totalNum, String orderNum, String shopName, String scene, String sceneInfo, String openId,Integer userId,HttpServletRequest request) {
        String temp = "";
        ShopSecret secret = shopSecretMapper.getSecret(shopId);
        SortedMap<String, Object> packageParams = new TreeMap();
        String nonceStr = DateFormatHelper.getCurTimestamp().toString();
        String Ip = Util.getIpAddr(request);
        String totalFee = Util.getMoney(totalNum.toString());
        packageParams.put("appid", wxConfig.getAppId());
        packageParams.put("attach", userId.toString());
        packageParams.put("body", shopName);
        packageParams.put("mch_id", secret.getShopPartner());
        packageParams.put("nonce_str", nonceStr);
        packageParams.put("notify_url", wxConfig.getRedirectUrl());
        packageParams.put("out_trade_no", orderNum);
        packageParams.put("spbill_create_ip", Ip);
        packageParams.put("total_fee", totalFee);
        if ("APP".equals(scene)) {
            packageParams.put("trade_type", "APP");
        } else if ("H5".equals(scene)) {
            packageParams.put("trade_type", "MWEB");
            packageParams.put("scene_info", sceneInfo);
            temp = "<scene_info>" + sceneInfo + "</scene_info>";
        } else if ("JSAPI".equals(scene)) {
            packageParams.put("trade_type", "JSAPI");
            packageParams.put("openid", openId);
            temp = "<openid>" + openId + "</openid>";
        }

        RequestHandler requestHandler = new RequestHandler(null, null);
        requestHandler.init(wxConfig.getAppId(), wxConfig.getAppSecret(), secret.getShopPartnerkey(), secret.getShopPartner());
        String sign = requestHandler.createSign(packageParams);

        String xml = "<xml>" +
                "<appid>" + wxConfig.getAppId() + "</appid>" +
                "<attach>" + orderNum + "</attach>" +
                "<body><![CDATA[" + shopName + "]]></body>" +
                "<mch_id>" + secret.getShopPartner() + "</mch_id>" +
                "<nonce_str>" + nonceStr + "</nonce_str>" +
                "<notify_url>" + wxConfig.getRedirectUrl() + "</notify_url>" +
                "<out_trade_no>" + orderNum + "</out_trade_no>" +
                "<spbill_create_ip>" + Ip + "</spbill_create_ip>" +
                "<sign>" + sign + "</sign>" +
                "<total_fee>" + totalFee + "</total_fee>" +
                "<trade_type>" + scene + "</trade_type>" +
                temp +
                "</xml>";


        String prePayId = "";
        String result = PayUtil.httpRequest(wxConfig.getCreatedOrderURL(), "POST", xml);
        SortedMap<String, Object> finalpackage = new TreeMap();
        try {
            Map map = PayUtil.doXMLParse(result);
            String str = String.valueOf(System.currentTimeMillis());
            String returnCode = map.get("return_code").toString();
            if (returnCode.equals("SUCCESS")) {
                prePayId = map.get("prepay_id").toString();
                finalpackage.put("appid", wxConfig.getAppId());
                finalpackage.put("noncestr", str);
                finalpackage.put("package", "Sign=WXPay");
                finalpackage.put("partnerid", secret.getShopPartner());
                finalpackage.put("prepayid", prePayId);
                finalpackage.put("timestamp", str);
                String finalSign = requestHandler.createSign(finalpackage);
                finalpackage.put("sign", finalSign);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap();
        map.put("finalPackage", finalpackage);

        //将订单传入队列中

        return map;
    }

    @Async
    public void groupOn(String orderNum) {
        //查询团购需要的相关数据
        Map<String, Object> map = orderService.detailByGroupOn(orderNum);
        //调用服务
        seckillService.groupOnLogic(map);
    }


}
